/*
 * Tencent is pleased to support the open source community by making QMUI_Android available.
 *
 * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the MIT License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qmuiteam.qmui.arch.scheme

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import com.qmuiteam.qmui.QMUILog
import com.qmuiteam.qmui.arch.QMUIFragment
import com.qmuiteam.qmui.arch.QMUIFragmentActivity
import com.qmuiteam.qmui.arch.R

interface QMUISchemeFragmentFactory {
    fun factory(fragmentCls: Class<out QMUIFragment>, bundle: Bundle?): QMUIFragment?
    fun factory(scheme: Map<String, SchemeValue>?, origin: String): Bundle?
    fun proxy(intent: Intent): Intent

    fun startActivities(activity: Activity, intent: List<Intent>, schemeInfo: List<SchemeInfo>)
    fun startFragmentAndDestroyCurrent(activity: QMUIFragmentActivity, fragment: QMUIFragment, schemeInfo: SchemeInfo): Int
    fun startFragment(activity: QMUIFragmentActivity, fragment: List<QMUIFragment>, schemeInfo: List<SchemeInfo>): Int
    fun shouldBlockJump(
        activity: Activity,
        fragmentCls: Class<out QMUIFragment>,
        scheme: Map<String, SchemeValue>?
    ): Boolean
}


open class QMUIDefaultSchemeFragmentFactory : QMUISchemeFragmentFactory {
    override fun factory(
        fragmentCls: Class<out QMUIFragment>,
        bundle: Bundle?
    ): QMUIFragment? {
        return try {
            val fragment = fragmentCls.newInstance()
            fragment.arguments = bundle
            fragment
        } catch (e: Exception) {
            QMUILog.printErrStackTrace(
                QMUISchemeHandler.TAG, e,
                "Error to create fragment: %s", fragmentCls.simpleName
            )
            null
        }
    }

    override fun factory(scheme: Map<String, SchemeValue>?, origin: String): Bundle? {
        val bundle = Bundle()
        bundle.putBoolean(QMUISchemeHandler.ARG_FROM_SCHEME, true)
        bundle.putString(QMUISchemeHandler.ARG_ORIGIN_SCHEME, origin)
        if (scheme != null && scheme.isNotEmpty()) {
            for ((name, schemeValue) in scheme) {
                when (schemeValue.type) {
                    Integer.TYPE -> bundle.putInt(name, schemeValue.value as Int)
                    java.lang.Boolean.TYPE -> bundle.putBoolean(name, schemeValue.value as Boolean)
                    java.lang.Long.TYPE -> bundle.putLong(name, schemeValue.value as Long)
                    java.lang.Float.TYPE -> bundle.putFloat(name, schemeValue.value as Float)
                    java.lang.Double.TYPE -> bundle.putDouble(name, schemeValue.value as Double)
                    else -> bundle.putString(name, schemeValue.origin)
                }
            }
        }
        return bundle
    }

    override fun proxy(intent: Intent): Intent {
        return intent
    }

    override fun startActivities(activity: Activity, intent: List<Intent>, schemeInfo: List<SchemeInfo>) {
        if (intent.size == 1) {
            activity.startActivity(intent[0])
        } else {
            activity.startActivities(intent.toTypedArray())
        }
    }

    override fun startFragmentAndDestroyCurrent(activity: QMUIFragmentActivity, fragment: QMUIFragment, schemeInfo: SchemeInfo): Int {
        return activity.startFragmentAndDestroyCurrent(fragment, true)
    }

    override fun startFragment(activity: QMUIFragmentActivity, fragment: List<QMUIFragment>, schemeInfo: List<SchemeInfo>): Int {
        return activity.startFragments(fragment)
    }

    override fun shouldBlockJump(
        activity: Activity,
        fragmentCls: Class<out QMUIFragment>,
        scheme: Map<String, SchemeValue>?
    ): Boolean {
        return false
    }
}